package org.jasig.cas.authentication;

import javax.validation.constraints.NotNull;

import org.jasig.cas.adaptors.jdbc.AbstractJdbcUsernamePasswordAuthenticationHandler;
import org.jasig.cas.authentication.handler.AuthenticationException;
import org.jasig.cas.authentication.principal.UsernamePasswordCredentials;
import org.jasig.cas.util.PasswordUtil;
import org.springframework.dao.IncorrectResultSizeDataAccessException;
/**
 * 重新实现AuthenticationHandler
 * @author admin
 *
 */
public class QueryDatabaseSaltAuthenticationHandler extends AbstractJdbcUsernamePasswordAuthenticationHandler {
	
	//盐值sql语句
	private String saltSql;
	
	private boolean strict=true;

	@NotNull
	private String sql;

	@SuppressWarnings("deprecation")
	protected final boolean authenticateUsernamePasswordInternal(final UsernamePasswordCredentials credentials) throws AuthenticationException {
		final String username = getPrincipalNameTransformer().transform( credentials.getUsername());
		final String salt=getSalt(username);
		final String password;
		if(salt==null || "".equals(salt)){
			password = credentials.getPassword();
		}else{
			password = PasswordUtil.mergePasswordAndSalt(credentials.getPassword(), salt, strict);
		}
		final String encryptedPassword = this.getPasswordEncoder().encode(password);
		try {
			final String dbPassword = getJdbcTemplate().queryForObject(this.sql, String.class, username);
			return dbPassword.equals(encryptedPassword);
		} catch (final IncorrectResultSizeDataAccessException e) {
			// this means the username was not found.
			return false;
		}
	}

	/**
	 * @param sql
	 * The sql to set.
	 */
	public void setSql(final String sql) {
		this.sql = sql;
	}

	@SuppressWarnings("deprecation")
	private String getSalt(String username) {
		if (saltSql == null || "".equals(saltSql)) {
			return null;
		} else {
			final String salt = getJdbcTemplate().queryForObject(saltSql,String.class, username);
			return salt;
		}
	}

	public String getSaltSql() {
		return saltSql;
	}

	public void setSaltSql(String saltSql) {
		this.saltSql = saltSql;
	}
	
    public boolean isStrict() {
		return strict;
	}

	public void setStrict(boolean strict) {
		this.strict = strict;
	}
}
